﻿using beway.common;
using Beway.ValueAdded.Model;
using Beway.ValueAdded.Model.ViewModel;
using Beway.ValueAdded.Service;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Mvc;

namespace Beway.ValueAdded.Admin.Controllers
{
    /// <summary>
    /// 批量充值处理类
    /// </summary>
    public class BatchController:BaseController
    {
        RechargeServ rechSvc = SingletonProvider<RechargeServ>.Instance;
        AdminUserServ admSvc = SingletonProvider<AdminUserServ>.Instance;
        ReUserServ ruServ = SingletonProvider<ReUserServ>.Instance;
        BatchDetailSvc batchDetailSvc = SingletonProvider<BatchDetailSvc>.Instance;
        BatchRechargeSvc batchRechSvc = SingletonProvider<BatchRechargeSvc>.Instance;
        SmsLogSvc smsLogSvc = SingletonProvider<SmsLogSvc>.Instance;

        public static readonly object locker = new object();

        #region 批次信息
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult BatchList(int? page, int? rows, int? reUserId,int? batchStatus,string batchName,DateTime? beginTime,DateTime? endTime,int? uploadUserId)
        {
            int ListCount = 0;
            int adminId = 0;
            if (CurrentRole == ManagerRoleType.MerchantAdmin || CurrentRole == ManagerRoleType.BatchRechAdmin)
            {
                adminId = CurrentAdmin.AdminID;
               
            }
            var d = batchRechSvc.List(page ?? 0, rows ?? 0, reUserId ?? 0, batchStatus??-1, batchName,beginTime,endTime,uploadUserId ?? 0, adminId, out ListCount);

            Dictionary<string, object> json = new Dictionary<string, object>();
            json.Add("total", ListCount);
            json.Add("rows", d);
            return Json(json, JsonRequestBehavior.AllowGet);
        }


        public ActionResult BatchListExport(int? reUserId, int batchStatus, string batchName, DateTime beginTime, DateTime endTime, int? uploadUserId)
        {
            int ListCount = 0;
            int adminId = 0;
            if (CurrentRole == ManagerRoleType.MerchantAdmin || CurrentRole == ManagerRoleType.BatchRechAdmin)
            {
                adminId = CurrentAdmin.AdminID;
            }
            var d = batchRechSvc.List(1 , 100000000, reUserId ?? 0, batchStatus, batchName, beginTime, endTime, uploadUserId ?? 0, adminId, out ListCount);
            string filename = "batch" + beway.common.FileUtil.GetFileNameFromSystemAuto();

            return new ExcelResult<BatchRechargeView>(d.ToList(), filename);
        }

        /// <summary>
        /// 批次充值 BatchStatus(0待充值，1正在充值中，2部分成功，3全部成功)
        /// </summary>
        /// <param name="batchId">批次id</param>
        /// <returns></returns>
        public JsonResult BatchRech(int batchId)
        {
            bool ret = false;
            string msg = "";
            if (CurrentRole == ManagerRoleType.SystemAdmin)
            {
                var m = batchRechSvc.Get(batchId);
                if (m != null)
                {
                    if (m.BatchStatus == 2 || m.BatchStatus == 0) //2为部分成功，0为未充值
                    {
                        //查找所有待充值记录
                        List<BatchDetail> list = batchDetailSvc.GetListByBatchId(m.Id).Where(r => r.RechStatus != 1).ToList();

                        decimal totalAmt = list.Sum(l => l.RechValue.Value);
                        var user = ruServ.GetByUserId(m.ReUserId.Value);
                        int iRet;
                        bool isvalidate = userValidate(totalAmt, user, out iRet);//客户身份验证
                        if (isvalidate)
                        {
                            Thread thread = new Thread(delegate () { recharge(list, m); });//匿名委托，实现带参数线程
                            thread.IsBackground = true;
                            thread.Start();
                            ret = true;
                            msg = "后台进程已进行充值，请稍后查询充值情况，当前页面可以关闭。";

                            m.BatchStatus = 1; //正在处理中
                            batchRechSvc.Update(m);
                        }
                        else
                        {
                            msg = "此项目余额不足，无法进行充值。";
                        }
                    }
                    else if (m.BatchStatus == 1)
                    {
                        msg = "充值已经在处理了，请稍后查询充值情况";
                    }
                    else if (m.BatchStatus == 3)
                    {
                        msg = "充值已全部完成，不能再次充值！";
                    }
                }
            }
            else
            {
                msg = "只有管理员才可以充值！";
            }
            Dictionary<string, object> json = new Dictionary<string, object>();
            json.Add("ret", ret);
            json.Add("msg", msg);
            return Json(json, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 批次审核，如果是通过状态，后台进程将进行充值（页面可关闭，但iis回收进程后充值会中断，需要后期核实充值状态）
        /// </summary>
        /// <param name="id">批次id</param>
        /// <param name="checkStatus">状态0待审核，1已审核，-1拒绝</param>
        /// <returns></returns>
        public JsonResult BatchCheck(int id,int checkStatus)
        {
            bool ret = false;
            string msg = "";
            if (CurrentRole == ManagerRoleType.SystemAdmin)
            {
                lock (locker) //锁住，防止并发进入，造成多次充值问题
                {
                    var m = batchRechSvc.Get(id);
                    if (m != null)
                    {                       
                        int originalStatus = m.CheckStatus.Value;
                        m.CheckStatus = checkStatus;
                        m.CheckUserId = CurrentAdmin.AdminID;
                        m.ProcessTime = DateTime.Now;

                        batchRechSvc.Update(m);
                        //批量充值
                        if (originalStatus != 1 && checkStatus == 1)
                        {
                            //查找所有待充值记录
                            List<BatchDetail> list = batchDetailSvc.GetListByBatchId(m.Id).Where(r => r.RechStatus != 1).ToList();

                            decimal totalAmt = list.Sum(l => l.RechValue.Value);
                            var user = ruServ.GetByUserId(m.ReUserId.Value);
                            int iRet;
                            bool isvalidate = userValidate(totalAmt, user, out iRet);//客户身份验证
                            if (isvalidate)
                            {
                                Thread thread = new Thread(delegate () { recharge(list, m); });//匿名委托，实现带参数线程
                                thread.IsBackground = true;
                                thread.Start();
                                ret = true;
                                msg = "后台进程已进行充值，请稍后查询充值情况，当前页面可以关闭。";
                                //标记当前批次正在充值中
                                m.BatchStatus = 1; //正在处理中
                                batchRechSvc.Update(m);
                            }
                            else
                            {
                                msg = "此项目余额不足，无法进行充值。";
                            }
                        }
                        else
                        {
                            ret = true;
                            msg = "处理成功！";
                        }
                    }
                    else
                    {
                        msg = "抱歉，批次不存在。";
                    }
                }
            }
            else
            {
                msg = "只有管理员才可以审核！";
            }


            Dictionary<string, object> json = new Dictionary<string, object>();
            json.Add("ret", ret);
            json.Add("msg", msg);
            return Json(json, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 充值验证方法
        /// </summary>
        /// <param name="rechAmt"></param>
        /// <param name="user"></param>
        /// <param name="ret"></param>
        /// <returns></returns>
        private bool userValidate( decimal rechAmt, ReUser user, out int ret)
        {
            ret = 10;
            bool isValidate = false;
            if (user != null && user.UserID > 0)
            {
                if (user.RechStatus > 0) //是否禁用
                {
                    DateTime now = DateTime.Now;
                    if (user.BeginTime < now && user.EndTime >= now)
                    {
                        //如果剩余额度小于等于预警额度，需要给项目经理发送短信提醒(30分钟一次)
                        if ((user.RechStock - rechAmt) <= user.RechAlarm && user.AdminId != null && user.AdminId > 0) //达到预警额
                        {
                            var adm = admSvc.FirstAdminById(user.AdminId.Value);
                            SmsLog sl = new SmsLog()
                            {
                                AdminId = user.AdminId,
                                Mobile = adm.Mobile,
                                ReUserId = user.UserID,
                                SendStatus = 0,
                                SendTime = System.DateTime.Now,
                                SmsContent = "瀚微充值平台-项目" + user.UserTitle + "预算额度剩余" + (user.RechStock - rechAmt) + "元，请及时处理",
                                SmsType = (int)SmsTypeEnum.SysSms
                            };
                            smsLogSvc.SendAlarmSms(sl);
                        }
                        //判断额度
                        if (user.RechStock > rechAmt)
                        {
                            isValidate = true;
                        }
                        else
                        {
                            ret = -7;//总额度不足
                        }
                    }
                    else
                    {
                        ret = -6; //不在有效期
                    }
                }
                else
                {
                    ret = -4;//账户禁用
                }
            }
            else
            {
                ret = -1; //账户不存在
            }
            return isValidate;
        }

        /// <summary>
        /// thread后台运行的充值服务
        /// </summary>
        /// <param name="list"></param>
        private void recharge(List<BatchDetail> list, BatchRecharge br)
        {
            int ret = -10;
            ReUser user = ruServ.GetByUserId(br.ReUserId.Value);
            int total = 0;
            LogManager.Write("***begin rech，total:"+list.Count);
            foreach (var bd in list)
            {
                LogManager.Write(total + " mobileno:" + bd.MobileNum + " " + bd.RechValue);
                int rechargeAmount = bd.RechValue.Value;
                string orderID = "RE" + beway.common.FileUtil.GetFileNameFromSystemAuto() + user.UserID.ToString();
                Model.Recharge rm = new Model.Recharge()
                {
                    UserID = user.UserID,
                    OrderAmount = rechargeAmount,
                    UserOrderNo = orderID,//调用系统提供的订单号
                    OrderID = orderID,
                    OrderTime = System.DateTime.Now,
                    PayStatus = 0,
                    RCTarget = bd.MobileNum,
                    RCType = 1, //话费
                    RechargeErrorReason = "",
                    RechargeStatus = 0,
                    RechargeAmount = rechargeAmount
                };
                int rcid = rechSvc.AddForUniqueOrderNo(rm);
                //int rcid = 1; //1 测试阶段，不更新 (3个地方)
                if (rcid > 0)
                {
                    //更新项目的额度（有可能与实际的总额度有出入，为考虑性能，未做精准控制）
                    user.RechStock -= rechargeAmount;
                    ruServ.UpdateStock(user);

                    //调用充值接口
                    string reRet = rechSvc.RechargeTrade(rm, user); //0充值中,  1成功, 9充值失败，可以退款, 11运营商维护，暂不能充值
                    //string reRet = "";//2 测试阶段，不充值
                    LogManager.Write("rech result:" + reRet);
                    if (reRet == "")//系统异常
                    {
                        ret = -3;//充值平台异常,返回retcode为空
                    }
                    else
                    {
                        //ret 1成功,2充值中,3失败
                        if (reRet == "0") //充值中
                        {
                            ret = 2;
                        }
                        else if (reRet == "1")//成功
                        {
                            ret = 1;
                        }
                        else if (reRet == "9")//充值失败，可以退款
                        {
                            ret = 3;
                        }
                        else if (reRet == "11")//运营商维护，暂不能充值
                        {
                            ret = 3;
                        }
                        else
                        {
                            ret = 3;
                        }
                    }
                    //充值结果更新到BatchDetail
                    bd.RechTime = DateTime.Now;
                    if (ret == 1 || ret == 2) //成功
                    {
                        //更新rechdetail
                        bd.RechStatus = 1; //充值成功                           
                    }
                    else
                    {
                        bd.RechStatus = 2;//充值失败
                        if (reRet == "11")
                        {
                            bd.RechMsg = "运营商维护，暂不能充值";
                        }
                        else
                        {
                            bd.RechMsg = string.Format("失败原因: {0}(欧飞错误码)", reRet);
                        }
                    }
                    batchDetailSvc.Update(bd); //保存修改

                    //更新充值结果 --3 测试不更新
                    rechSvc.Update(rm);

                    total++;
                }
                else
                {
                    ret = 0;//订单号已存在，请更换
                }
            }
            //判断是否全部处理完成
            br.ProcessTime = DateTime.Now;
            if (list.Count() == total)
            {
                br.BatchStatus = 3;//全部处理完成
            }
            else
            {
                br.BatchStatus = 2;//部分处理完成
            }
            batchRechSvc.Update(br);
        }
        #endregion

        #region 上传
        public ActionResult Upload()
        {
            
            return View();
        }

        [HttpPost]
        public ActionResult Upload(ReUser model)
        {
            int reUserId = 0;           
            int.TryParse(Request["projectId"], out reUserId);
            if (reUserId > 0)
            {
                HttpPostedFileBase upfile = Request.Files["importFile"];
                string filename = "";
                if (upfile.ContentLength > 0)
                {
                    string savepath = System.Configuration.ConfigurationManager.AppSettings["BatchFilePath"];
                    if (!Directory.Exists(savepath))
                    {
                        Directory.CreateDirectory(savepath);
                    }
                    filename = beway.common.FileUtil.GetFileNameFromSystemAuto();
                    filename += Path.GetExtension(upfile.FileName);
                    upfile.SaveAs(savepath + filename);

                    string err = "";
                    DataTable dt = Excel.GetExeclToDataTable(savepath + filename, "Sheet1", out err);
                    if (err == "" && dt != null)
                    {
                        //判断是否包含要求的字段
                        if (dt.Columns.Contains("手机号") && dt.Columns.Contains("充值金额"))
                        { }
                        else
                        {
                            ModelState.AddModelError("", "导入文档字段与要求不符！");
                            return View();
                        }
                        List<BatchDetail> list = new List<BatchDetail>();
                        BatchDetail bd;
                        StringBuilder resultList = new StringBuilder();

                        string mobile;
                        int amount=0;

                        foreach (DataRow r in dt.Rows)
                        {
                            mobile = r["手机号"].ToString();
                            int.TryParse(r["充值金额"].ToString(),out amount);
                            if (mobile != "" && amount > 0)
                            {
                                bd = new BatchDetail();
                                bd.AddTime = DateTime.Now;
                                bd.BatchId = 0;
                                bd.MobileNum = mobile;
                                bd.RechMsg = "";
                                bd.RechStatus = 0;
                                bd.RechValue = amount; 
                                list.Add(bd); 
                            }
                        }
                        if (list.Count > 0)
                        {
                            //增加批次信息
                            BatchRecharge br = new BatchRecharge();
                            br.AddTime = System.DateTime.Now;
                            br.Amount = list.Sum(m => m.RechValue);
                            br.BatchStatus = 0; //未充值
                            br.CheckStatus = 0; //未审核
                            br.FileName = filename;
                            br.ReUserId = reUserId; //项目的id
                            br.Total = list.Count;
                            br.UploadUserId = CurrentAdmin.AdminID;
                            br.BatchName =DateTime.Now.ToString("yyyyMMddHHmmss");
                            
                            int addCount = batchDetailSvc.BatchAdd(list,br);
                            if (addCount > 0)
                            {
                                err = String.Format("成功导入{0}条记录", list.Count);
 
                            }
                            else
                            {
                                err = "导入失败，请重试！";
                            }

                        }
                        else
                        {
                            err = "上传文件中没有有效数据！";
                        }


                        ModelState.AddModelError("", err);
                    }
                    else
                    {
                        if (err.Length == 0)
                        {
                            err = "不包含数据";
                        }
                        ModelState.AddModelError("", "上传文件出错，信息：" + err);
                    }
                }
                else
                {
                    ModelState.AddModelError("", "上传文件不能为空！");
                }
            }
            else
            {
                ModelState.AddModelError("", "请选择所属项目！");
            }

            return View();
        }
        #endregion

        #region 详细
        public ActionResult Detail()
        {
            return View();
        }
 

        public JsonResult DetailList(int? page, int? rows, int? reUserId, string batchName, string mobileNum, int? rechStatus, int? uploadUserId)
        {
            int ListCount = 0;
            int adminId = 0;
            if (CurrentRole == ManagerRoleType.MerchantAdmin || CurrentRole == ManagerRoleType.BatchRechAdmin)
            {
                adminId = CurrentAdmin.AdminID;
            }
            var d = batchDetailSvc.List(page ?? 0, rows ?? 0, reUserId??0, batchName, mobileNum, rechStatus ?? 0, uploadUserId??0, adminId,out ListCount);

            Dictionary<string, object> json = new Dictionary<string, object>();
            json.Add("total", ListCount);
            json.Add("rows", d);
            return Json(json, JsonRequestBehavior.AllowGet);
        }


        public ActionResult DetailExport(int? reUserId, string batchName, string mobileNum, int? rechStatus, int? uploadUserId)
        {
            int ListCount = 0;
            int adminId = 0;
            if (CurrentRole == ManagerRoleType.MerchantAdmin || CurrentRole == ManagerRoleType.BatchRechAdmin)
            {
                adminId = CurrentAdmin.AdminID;
            }
            var d = batchDetailSvc.List(1, 100000000, reUserId ?? 0, batchName, mobileNum, rechStatus ?? 0, uploadUserId ?? 0, adminId, out ListCount);

            string filename = "batchlist" + beway.common.FileUtil.GetFileNameFromSystemAuto();
            return new ExcelResult<BatchDetailView>(d.ToList(), filename);
        }

        #endregion
    }
}